#pragma once

#include "Logger.hpp"
#include"Util.hpp"
#include <iostream>
#include <sys/epoll.h>
#include <unistd.h>

// 此处直接实现epoll 版本的多路转接
class Epoller
{
    int OperEpollHeapler(int sockfd , uint32_t events , int oper)
    {
        epoll_event ev;
        ev.data.fd = sockfd;
        ev.events = events;
        return epoll_ctl(_epfd, oper, sockfd, &ev);
    }

public:
    // 创建、三个操作、析构时释放fd
    Epoller() : _epfd(-1)
    {
        // 在构造的时候创建epoll模型
        // epoll_create 返回文件描述符，即返回epoll 模型
        _epfd = epoll_create(128); // 参数代表底层红黑树的节点个数，现在已经被忽略了，随便填写一个正数就可以了
        // 成功返回0，失败返回-1
        if (_epfd < 0)
        {
            LOG(LogLevel::FATAL) << "epoll 模型创建失败";
            exit(1);
        }
        LOG(LogLevel::INFO) << "epoll 模型创建成功";
    }
    void AddEvent(int sockfd, uint32_t events)
    {
        // epoll_event ev;
        // ev.data.fd = sockfd;
        // ev.events = events;
        // // 调用epoll_ctl
        // int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, sockfd, &ev);
        int n = OperEpollHeapler(sockfd , events , EPOLL_CTL_ADD);
        // 判断返回值；epoLl_ctl 成功返回0，失败返回-1
        if (n < 0)
        {
            LOG(LogLevel::ERROR) << "add：" << sockfd << " , events: " << Events2String(events) << "to epoller failed";
            return;
        }
        LOG(LogLevel::INFO) << "add：" << sockfd << " , events: " << Events2String(events) << "to epoller success";
    }
    void DelEvent(int sockfd)
    {
        int n = epoll_ctl(_epfd , EPOLL_CTL_DEL , sockfd , nullptr);
        if (n < 0)
        {
            LOG(LogLevel::ERROR) << "Del：" << sockfd  << " failed";
            return;
        }
        LOG(LogLevel::INFO) << "Del：" << sockfd << " success";
    }
    void ModEvent(int sockfd, uint32_t events)
    {
        // 将fd 关心的事件设置进epoll 中，调用epoll_ctl
        // epoll_event ev;
        // ev.data.fd = sockfd;
        // ev.events = events;
        // int n = epoll_ctl(_epfd, EPOLL_CTL_MOD, sockfd, &ev);
        int n = OperEpollHeapler(sockfd , events , EPOLL_CTL_MOD);
        if (n < 0)
        {
            LOG(LogLevel::ERROR) << "Mod:" << sockfd << " , events: " << Events2String(events) << "to epoller failed";
            return;
        }
        LOG(LogLevel::INFO) << "Mod:" << sockfd << " , events: " << Events2String(events) << "to epoller success";

    }
    int wait(struct epoll_event revs[], int num, int timeout)
    {
        // int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
        int n = epoll_wait(_epfd, revs, num, timeout);
        // 返回值大于0表示就绪的事件个数，为0就是意味着没有事件就绪；小于0表示出错；
        if (n == 0)
        {
            LOG(LogLevel::DEBUG) << "没有事件就绪";
        }
        else if (n < 0)
        {
            LOG(LogLevel::WARNING) << "epoll_wait 出错";
        }
        else
        {
            LOG(LogLevel::INFO) << "有" << n << "个事件就绪";
        }
        return n;
    }
    ~Epoller()
    {
        // 析构的时候释放epfd
        if (_epfd >= 0)
        {
            close(_epfd);
        }
    }

private:
    int _epfd;
};